# -*- coding: utf-8 -*-
# @Time    : 2024/8/29 0:13
# @Author  : Alvin
# @File    : users.py

from flask import current_app
from sqlalchemy import Column, Integer, String, ForeignKey, SmallInteger, orm
from sqlalchemy.orm import Relationship

from app.libs.error_code import AuthFailed
from app.libs.session import generate_session
from app.models.base import Base, db
from app.models.sessions import Session
from app.validators.forms import UserMinaForm


class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    wechat_open_id = Column(String(50),nullable=False)
    schools = Relationship('School')
    colleges = Relationship('College')
    majors = Relationship('Major')
    school_id = Column(Integer, ForeignKey('schools.school_id'))
    college_id = Column(Integer, ForeignKey('colleges.college_id'))
    major_id = Column(Integer, ForeignKey('majors.major_id'))
    nickname = Column(String(50))
    avatar = Column(String(255))
    phone = Column(String(15), unique=True)
    email = Column(String(24), unique=True)
    # registration_date = Column(DateTime, default=datetime.utcnow)
    points_balance = Column(Integer, default=0)
    # user_status = Column(String(20))
    gender = Column(String(10))
    # region = Column(String(50))
    # last_login_time = Column(DateTime)
    identity_category = Column(SmallInteger, default=1)  # 1为普通用户 2为管理员

    @orm.reconstructor
    def __init__(self):
        self.fields = ['id',
                       'nickname',
                       'avatar','phone', 'email', 'points_balance',
                       'gender', 'create_datetime']
        # print("fields initialized:", self.fields)  # 打印



    @staticmethod
    def verify_by_email(email, password):
        user = User.query.filter_by(email=email).first_or_404(msg='用户未注册')
        if not user.check_password(password):
            raise AuthFailed()
        scope = 'AdminScope' if user.auth == 2 else 'UserScope'
        return {'uid': user.id, 'scope': scope}

    @classmethod
    def verify_by_code(cls, code, password):
        # 优化， 登录的时候check是否有用户，没有则创建同时创建新session，如果有则查看是否有session并且是否过期
        # 这里password只是为了适配全面传来的账号密码， 但是小程序登录只需要code
        wx_app_id = current_app.config.get('MINA_APP_ID')
        wx_secret = current_app.config.get('MINA_APP_SECRET')
        result = generate_session(wx_app_id, wx_secret, code)
        # 获取用户openid
        open_id = result['openid']
        session_key = result['session_key']
        user = User.query.filter_by(wechat_open_id=open_id).first()
        if not user:
            # 注册用户
            user = cls.register_by_code(open_id)
        session_obj = Session.query.filter_by(session_token=session_key).first()
        if not session_obj:
            # 如果之前存在的session_token，且和现在生成的session_token不一样，则先删除之前的
            session_ori_obj = Session.query.filter_by().first()
            if session_ori_obj:
                # 如果原先存在，就需要先删除旧的
                Session.delete_session(session_ori_obj.session_token)
            # 没有该新生成的session则插入
            Session.create_session(user.id, session_key)
        scope = 'AdminScope' if user.identity_category == 2 else 'UserScope'
        return {'uid': user.id, 'scope': scope}

    @staticmethod
    def register_by_code(open_id):
        form = UserMinaForm().validate_for_api()

        with db.auto_commit():
            user = User()
            user.nickname = form.nickName.data
            user.avatar = form.avatarUrl.data
            user.wechat_open_id = open_id
            db.session.add(user)
        return User.query.filter_by(wechat_open_id=open_id).first()

    def update_balance_points(self, points_balance):
        with db.auto_commit():
            self.points_balance = points_balance

    def verify_by_openid(self):
        pass
